home *** CD-ROM | disk | FTP | other *** search
- ;
- ; parser.inc
- ;
- ;
- ; This INCLUDE file implements a PSP command line parser of
- ; the following command line syntax:
- ;
- ; <byte count> [leading delims][ / [cmd1 [cmd2 cmd3] / ][ <string> ]
- ;
- ; where:
- ;
- ; <byte count> is a mandatory one-byte count of the rest of
- ; the characters in the command line.
- ; The byte count may be zero (null cmd line).
- ;
- ; leading delims are leading blanks or tabs before the first
- ; slash or the first non-blank character of
- ; <string>.
- ;
- ; cmdi is the ith one-character command code following
- ; the first "/" encountered on the line. These
- ; commands are executed as they are encountered
- ; during the left-to-right parsing of the line.
- ;
- ; <string> all characters, including any blanks or tabs,
- ; that follow the second slash if present; or
- ; all characters that follow leading blanks or
- ; tabs, if no slashes are present.
- ;
- ;
- ; on entry, this code expects the following register values:
- ;
- ; SI = offset of the byte count (the first byte of the line)
- ;
- ; this code trashes the following registers:
- ;
- ; AX, BX, CX, DX, possibly BP
- ;
- ; this parser discards any leading delimiters up to the first optional
- ; slash. It then decodes and executes any valid one-character commands
- ; found between the first and second slash encountered. The definition
- ; and execution of the commands is table driven, a table interface is
- ; provided by the host program that INCLUDEs this code. When the second
- ; slash is encountered, parsing is done. The CX register contains the
- ; number of string characters left after the second slash (including
- ; delimiters) or, if no slashes are encountered before the first non-
- ; delimiter, the number of string characters starting at the first non-
- ; delimiter. The BX register points to the corresponding character,
- ; relative to [SI].
- ;
- ; examples:
- ;
- ; null string parser finds no cmds CX = 0
- ; BX undefined
- ;
- ; <space><tab><space> parser finds no cmds CX = 0
- ; BX undefined
- ;
- ; / cmd1 parser executes cmd1 CX = 0
- ; BX undefined
- ;
- ; /<string> parser executes any valid CX = 0
- ; command characters found BX undefined
- ; in string
- ;
- ; /cmd1 cmd2/<tab><string> parser executes cmd1 and CX = count of
- ; cmd2. string +
- ; tab char
- ; BX points at tab
- ;
- ; <space><space><string> parser finds no commands CX = count of
- ; string only
- ; BX points at
- ; first char of
- ; string.
- ;
- ; This code expects the following table interface to be defined in the
- ; host code.
- ;
- ; CMD_TOTAL DW n ;total number of commands defined
- ;
- ; CMD_LETTERS DB 'cmd1','CMD1' ;two characters each of which
- ; . ; signify a command
- ; .
- ; DB 'cmdn','CMDn' ;(typically lower and upper case
- ; ; of one letter)
- ;
- ; CMD_OFFSETS DW offset_proc1 ;the corresponding procedure for
- ; . ;the command defined above
- ; .
- ; DW offset_procn ;(NEAR procedures in host code)
- ;
- ; symbols defined within the INCLUDE code will have a leading "_"
- ;
- ; equates
- ;
- _TAB EQU 9 ;ascii TAB code
- _BLANK EQU ' ' ;ascii BLANK code
- _SLASH EQU '/' ;ascii '/' code
- ;
- ; start the parse
- ;
- ; if command line is empty, skip parsing, report back that CX = 0
- ;
- ;
- _START_PARSE: SUB CX,CX ;zero CX
- MOV CL,[SI] ;get char count from 1st byte
- OR CL,CL ;is it zero?
- JZ _PARSE_DONE ;done if yes, CX = 0
- ;
- ; cmd line is not null
- ;
- ; set up loop indices: CX = number of chars left in string
- ; BX = index relative to [SI] of the
- ; next character to be tested
- ;
- SUB BX,BX ;initialize index (first iter
- ; of loop will increment BX
- ;
- ; parse leading blanks and tabs until either a "/" is found or else
- ; all leading blanks and tabs are discarded
- ;
- _PARSE_BLANKS: INC BX ;point to next character in line
- MOV AL,[SI][BX] ;next character into AL
- CMP AL,_BLANK ;is it blank?
- JZ _LOOP_BLANK ;keep parsing if yes
- CMP AL,_TAB ;is it tab?
- JZ _LOOP_BLANK ;keep parsing if yes
- CMP AL,_SLASH ;is it first slash?
- JZ _NEXT_CMD ;jump if yes, start decoding
- ; commands between slashes
- JMP _PARSE_DONE ;else first non-blank non-tab
- ;delimiter.
- ;
- ; leading blank or tab found, continue looking for leading delimiters
- ;
- _LOOP_BLANK: LOOP _PARSE_BLANKS
- JMP _PARSE_DONE
- ;
- ; parse next character after first slash
- ;
- _CMD_PARSE: MOV AL,[SI][BX] ;get next char in cmd line
- CMP AL,_SLASH ;is it second slash?
- JNE _CHECK_TABLES ;if not, go to tables to find
- ;the command.
- ;
- ; second slash found. parsing is done. point BX to next character and
- ; decrement CX so it equals characters left after second slash
- ;
- INC BX ;leave BX pointing to next char
- DEC CX ;leave CX as count of all chars
- ; after the second slash.
- JMP _PARSE_DONE ;and exit this parser code
- ;
- ; set up inner loop to search through CMD_LETTERS table for a match of
- ; command characters with char in AL. If not in table, ignore character
- ; in AL and parse next character in cmd line.
- ;
- _CHECK_TABLES: PUSH BX ;save outer loop context
- PUSH CX
- MOV CX,CMD_TOTAL ;table length for inner loop
- SUB BX,BX ;clear index
- ;
- ; for each CMD_LETTERS 2-byte entry, check both characters for a match
- ;
- _TABLE_LOOP: CMP AL,CMD_LETTERS[BX] ;does left byte match?
- JE _DO_CMD ;jump if yes, do command
- CMP AL,CMD_LETTERS[BX+1] ;else does right match?
- JNE _MORE_TABLE
- ;
- ; command "letter" matches AL. After saving context, enter host-
- ; supplied procedure indirectly through corresponding entry in
- ; CMD_OFFSETS table.
- ;
- _DO_CMD: PUSH AX ;save context
- PUSH BX
- PUSH CX
- PUSH SI
- CALL CMD_OFFSETS[BX] ;call indirect through table
- POP SI
- POP CX
- POP BX
- POP AX ;restore context
- JMP _MORE_PARSE ;parse next char
- ;
- ; else haven't matched AL yet, so look at next table entry in inner loop
- ;
- _MORE_TABLE: INC BX ;point to next word
- INC BX
- LOOP _TABLE_LOOP ;and loop on table length
- ;
- ; command definition table exhausted (so ignore this character) or
- ; character command was found in table and executed.
- ;
- ; restore outer loop context and parse the next character in line
- ;
- _MORE_PARSE: POP CX ;restore outer loop context
- POP BX
- _NEXT_CMD: INC BX ;point to next char in cmd line
- LOOP _CMD_PARSE ;parse until 2nd slash or CX=0
- ;
- ; CX is characters left after second slash
- ; or, characters left after leading delimiters if no slashes
- ; or, zero if no characters at all
- ; or, zero if no slashes and no non-blank or non-tab characters
- ; or, zero if no characters at all after second slash
- ;
- ; BX is pointing to corresponding character in string if CX > 0
- ; or, undefined if CX = 0
- ;
- _PARSE_DONE LABEL NEAR ;done
- ;
- ; ------------ end of parser.inc ------------
- ;
- DEC DX ; filename
- DEC DX
- FIND_FILE: MOV AH,4E